
package org.apache.mina.common;

import java.net.SocketAddress;

/**
 * A filter which intercepts {@link IoHandler} events like Servlet filters.
 * Filters can be used for these purposes:
 * <ul>
 * <li>Event logging,</li>
 * <li>Performance measurement,</li>
 * <li>Authorization,</li>
 * <li>Overload control,</li>
 * <li>Message transformation (e.g. encryption and decryption, ...),</li>
 * <li>and many more.</li>
 * </ul>
 * <p>
 * 
 * Filter：像servlet过滤器一样拦截IoHandler事件。为了以下的目的，可以使用过滤器：事件日志、性能测量、权限、负载控制、转化消息（如加密、
 * 解密）等。
 * 
 * <strong>Please NEVER implement your filters to wrap {@link IoSession}
 * s.</strong> Users can cache the reference to the session, which might
 * malfunction if any filters are added or removed later.
 * 
 * 千万不要在IoSession的实现类也同时实现了Filter，这是因为用户能缓存session的引用，这样当添加或移除过滤器时会造成错误。
 * 
 * <h3>The Life Cycle</h3>
 * {@link IoFilter}s are activated only when they are inside
 * {@link IoFilterChain}. IoFilter生命周期：当它们在IoFilterChain时，才是活动的。
 * <p>
 * 
 * 
 * 
 * When you add an {@link IoFilter} to an {@link IoFilterChain}:
 * <ol>
 * <li>{@link #init()} is invoked by {@link ReferenceCountingIoFilter} if the
 * filter is added at the first time.</li>
 * <li>{@link #onPreAdd(IoFilterChain, String, NextFilter)} is invoked to notify
 * that the filter will be added to the chain.</li>
 * <li>The filter is added to the chain, and all events and I/O requests pass
 * through the filter from now.</li>
 * <li>{@link #onPostAdd(IoFilterChain, String, NextFilter)} is invoked to
 * notify that the filter is added to the chain.</li>
 * <li>The filter is removed from the chain if
 * {@link #onPostAdd(IoFilterChain, String, org.apache.mina.common.IoFilter.NextFilter)}
 * threw an exception. {@link #destroy()} is also invoked by
 * {@link ReferenceCountingIoFilter} if the filter is the last filter which was
 * added to {@link IoFilterChain}s.</li>
 * </ol>
 * 当你添加IoFilter到一个IoFilterChain时：
 * 
 * 1：如果第一次添加该过滤器，在ReferenceCountingIoFilter中会调用init()方法。
 * 2：调用onPreAdd，通知：此filter将会被添加到过滤链中。 3：过滤器被添加到过滤链中，从现在开始，所有的事件和IO请求都将经过此过滤器。
 * 4：调用onPostAdd方法，并通知：该过滤器添加到了过滤链中。
 * 5：如果出现以下情况，过滤器将会被从过滤链中移除，如果onPostAdd抛错，如果这个过滤器是最后一个被加到过滤链的
 * ，则在ReferenceCountingIoFilter会调用destroy()方法。
 * <p>
 * 
 * 
 * When you remove an {@link IoFilter} from an {@link IoFilterChain}:
 * <ol>
 * <li>{@link #onPreRemove(IoFilterChain, String, NextFilter)} is invoked to
 * notify that the filter will be removed from the chain.</li>
 * <li>The filter is removed from the chain, and any events and I/O requests
 * don't pass through the filter from now.</li>
 * <li>{@link #onPostRemove(IoFilterChain, String, NextFilter)} is invoked to
 * notify that the filter is removed from the chain.</li>
 * <li>{@link #destroy()} is invoked by {@link ReferenceCountingIoFilter} if the
 * removed filter was the last one.</li>
 * </ol>
 * 
 * 当你从IoFilterChain中移除IoFilter时：
 * 
 * 1：调用onPreRemove()方法，告知：这个过滤器将从从过滤链中移除。 2：从链中移除过滤器，从现在开始，任何的事件和IO请求都不会经过此过滤器。
 * 3：调用onPostRemove()方法，告知：过滤器已经从过滤链中移除。
 * 4：如果被移除的过滤器是链中最后一个，在ReferenceCountingIoFilter中将会调用destory()方法。
 */
public interface IoFilter {
    /**
     * Invoked by {@link ReferenceCountingIoFilter} when this filter is added to
     * a {@link IoFilterChain} at the first time, so you can initialize shared
     * resources. Please note that this method is never called if you don't wrap
     * a filter with {@link ReferenceCountingIoFilter}.
     * 
     * 当该过滤器是第一次添加到IoFilterChain中时，ReferenceCountingIoFilter会调用此方法，因此，
     * 你可以在初始化一些资源 。 请注意：如果你的过滤器不是ReferenceCountingIoFilter，则该方法永远不会被调用。
     */
    void init() throws Exception;

    /**
     * Invoked by {@link ReferenceCountingIoFilter} when this filter is not used
     * by any {@link IoFilterChain} anymore, so you can destroy shared
     * resources. Please note that this method is never called if you don't wrap
     * a filter with {@link ReferenceCountingIoFilter}.
     * 
     * 当该过滤器不被任何IoFilterChain使用时，ReferenceCountingIoFilter将调用此方法，因此，你可以在此销毁一些资源。
     * 注意：如果你的过滤器不是ReferenceCountingIoFilter，则该方法永远不会被调用。
     */
    void destroy() throws Exception;

    /**
     * Invoked before this filter is added to the specified <tt>parent</tt>.
     * Please note that this method can be invoked more than once if this filter
     * is added to more than one parents. This method is not invoked before
     * {@link #init()} is invoked.
     * 
     * 在此过滤器添加到指定的parent前，调用该方法。
     * 注意：如果此过滤器添加个多个链中，则该方法会被多次调用。此方法不会在init()方法之前被调用。
     * 
     * @param parent
     *            the parent who called this method
     * @param name
     *            the name assigned to this filter
     * @param nextFilter
     *            the {@link NextFilter} for this filter. You can reuse this
     *            object until this filter is removed from the chain.
     */
    void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter)
            throws Exception;

    /**
     * Invoked after this filter is added to the specified <tt>parent</tt>.
     * Please note that this method can be invoked more than once if this filter
     * is added to more than one parents. This method is not invoked before
     * {@link #init()} is invoked.
     * 
     * 在此过滤器添加到指定的parent后，调用该方法。
     * 注意：如果此过滤器添加个多个链中，则该方法会被多次调用。此方法不会在init()方法之前被调用。
     * 
     * @param parent
     *            the parent who called this method
     * @param name
     *            the name assigned to this filter
     * @param nextFilter
     *            the {@link NextFilter} for this filter. You can reuse this
     *            object until this filter is removed from the chain.
     */
    void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter)
            throws Exception;

    /**
     * Invoked before this filter is removed from the specified <tt>parent</tt>.
     * Please note that this method can be invoked more than once if this filter
     * is removed from more than one parents. This method is always invoked
     * before {@link #destroy()} is invoked.
     * 
     * 在此过滤器从指定的parent移除前，调用该方法。
     * 注意：如果此过滤器添加个多个链中，则该方法会被多次调用。此方法一直在destory()前被调用。
     * 
     * @param parent
     *            the parent who called this method
     * @param name
     *            the name assigned to this filter
     * @param nextFilter
     *            the {@link NextFilter} for this filter. You can reuse this
     *            object until this filter is removed from the chain.
     * 
     */
    void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter)
            throws Exception;

    /**
     * Invoked after this filter is removed from the specified <tt>parent</tt>.
     * Please note that this method can be invoked more than once if this filter
     * is removed from more than one parents. This method is always invoked
     * before {@link #destroy()} is invoked.
     * 
     * 在此过滤器从指定的parent移除后，调用该方法。
     * 注意：如果此过滤器添加个多个链中，则该方法会被多次调用。此方法一直在destory()前被调用。
     * 
     * @param parent
     *            the parent who called this method
     * @param name
     *            the name assigned to this filter
     * @param nextFilter
     *            the {@link NextFilter} for this filter. You can reuse this
     *            object until this filter is removed from the chain.
     * 
     */
    void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter)
            throws Exception;

    /**
     * Filters {@link IoHandler#sessionCreated(IoSession)} event.
     * 过滤IoHandler.sessionCreated(IoSession)事件。
     */
    void sessionCreated(NextFilter nextFilter, IoSession session)
            throws Exception;

    /**
     * Filters {@link IoHandler#sessionOpened(IoSession)} event.
     * 过滤IoHandler.sessionOpened(IoSession)事件。
     */
    void sessionOpened(NextFilter nextFilter, IoSession session)
            throws Exception;

    /**
     * Filters {@link IoHandler#sessionClosed(IoSession)} event.
     * 过滤IoHandler.sessionClosed(IoSession)事件。
     */
    void sessionClosed(NextFilter nextFilter, IoSession session)
            throws Exception;

    /**
     * Filters {@link IoHandler#sessionIdle(IoSession,IdleStatus)} event.
     * 过滤IoHandler.sessionIdle(IoSession,IdleStatus)事件。
     */
    void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status)
            throws Exception;

    /**
     * Filters {@link IoHandler#exceptionCaught(IoSession,Throwable)} event.
     * 过滤IoHandler.exceptionCaught(IoSession,Throwable)事件。
     */
    void exceptionCaught(NextFilter nextFilter, IoSession session,
            Throwable cause) throws Exception;

    /**
     * Filters {@link IoHandler#messageReceived(IoSession,Object)} event.
     * 过滤IoHandler.messageReceived(IoSession,Object)事件。
     */
    void messageReceived(NextFilter nextFilter, IoSession session,
            Object message) throws Exception;

    /**
     * Filters {@link IoHandler#messageSent(IoSession,Object)} event.
     * 过滤IoHandler.messageSent(IoSession,Object)事件。
     */
    void messageSent(NextFilter nextFilter, IoSession session, Object message)
            throws Exception;

    /**
     * Filters {@link IoSession#close()} method invocation.
     * 过滤IoSession#close()方法的调用。
     */
    void filterClose(NextFilter nextFilter, IoSession session) throws Exception;

    /**
     * Filters {@link IoSession#write(Object)} method invocation.
     * 过小IoSession#write(Object)方法的调用。
     */
    void filterWrite(NextFilter nextFilter, IoSession session,
            WriteRequest writeRequest) throws Exception;

    /**
     * Represents the next {@link IoFilter} in {@link IoFilterChain}.
     * 封装IoFilterChain中的下一个IoFilter。
     */
    public interface NextFilter {
        /**
         * Forwards <tt>sessionCreated</tt> event to next filter.
         * 转发sessionCreated事件到下一个过滤器。
         */
        void sessionCreated(IoSession session);

        /**
         * Forwards <tt>sessionOpened</tt> event to next filter.
         * 转发sessionOpened事件到下一个过滤器。
         */
        void sessionOpened(IoSession session);

        /**
         * Forwards <tt>sessionClosed</tt> event to next filter.
         * 转发sessionClosed事件到下一个过滤器。
         */
        void sessionClosed(IoSession session);

        /**
         * Forwards <tt>sessionIdle</tt> event to next filter.
         * 转发sessionIdle事件到下一个过滤器。
         */
        void sessionIdle(IoSession session, IdleStatus status);

        /**
         * Forwards <tt>exceptionCaught</tt> event to next filter.
         * 转发exceptionCaught事件到下一个过滤器。
         */
        void exceptionCaught(IoSession session, Throwable cause);

        /**
         * Forwards <tt>messageReceived</tt> event to next filter.
         * 转发messageReceived事件到下一个过滤器。
         */
        void messageReceived(IoSession session, Object message);

        /**
         * Forwards <tt>messageSent</tt> event to next filter.
         * 转发messageSent事件到下一个过滤器。
         */
        void messageSent(IoSession session, Object message);

        /**
         * Forwards <tt>filterWrite</tt> event to next filter.
         * 转发filterWrite事件到下一个过滤器。
         */
        void filterWrite(IoSession session, WriteRequest writeRequest);

        /**
         * Forwards <tt>filterClose</tt> event to next filter.
         * 转发filterClose事件到下一个过滤器。
         */
        void filterClose(IoSession session);
    }

    /**
     * Forwards <tt>filterClose</tt> event to next filter.
     * 封装IoSession.write(Object)触发的发送请求。
     */
    public static class WriteRequest {
        private static final WriteFuture UNUSED_FUTURE = new WriteFuture() {
                                                           public boolean isWritten() {
                                                               return false;
                                                           }

                                                           public void setWritten(
                                                                   boolean written) {
                                                           }

                                                           public IoSession getSession() {
                                                               return null;
                                                           }

                                                           public void join() {
                                                           }

                                                           public boolean join(
                                                                   long timeoutInMillis) {
                                                               return true;
                                                           }

                                                           public boolean isReady() {
                                                               return true;
                                                           }

                                                           public void addListener(
                                                                   IoFutureListener listener) {
                                                               throw new IllegalStateException(
                                                                       "You can't add a listener to a dummy future.");
                                                           }

                                                           public void removeListener(
                                                                   IoFutureListener listener) {
                                                               throw new IllegalStateException(
                                                                       "You can't add a listener to a dummy future.");
                                                           }

                                                           public Object getLock() {
                                                               return this;
                                                           }
                                                       };

        private final Object             message;

        private final WriteFuture        future;

        private final SocketAddress      destination;

        /**
         * Creates a new instance without {@link WriteFuture}. You'll get an
         * instance of {@link WriteFuture} even if you called this constructor
         * because {@link #getFuture()} will return a bogus future.
         */
        public WriteRequest(Object message) {
            this(message, null, null);
        }

        /**
         * Creates a new instance with {@link WriteFuture}.
         */
        public WriteRequest(Object message, WriteFuture future) {
            this(message, future, null);
        }

        /**
         * Creates a new instance.
         * 
         * @param message
         *            a message to write
         * @param future
         *            a future that needs to be notified when an operation is
         *            finished
         * @param destination
         *            the destination of the message. This property will be
         *            ignored unless the transport supports it.
         */
        public WriteRequest(Object message, WriteFuture future,
                SocketAddress destination) {
            if (message == null) {
                throw new NullPointerException("message");
            }

            if (future == null) {
                future = UNUSED_FUTURE;
            }

            this.message = message;
            this.future = future;
            this.destination = destination;
        }

        /**
         * Returns {@link WriteFuture} that is associated with this write
         * request.
         */
        public WriteFuture getFuture() {
            return future;
        }

        /**
         * Returns a message object to be written.
         */
        public Object getMessage() {
            return message;
        }

        /**
         * Returne the destination of this write request.
         * 
         * @return <tt>null</tt> for the default destination
         */
        public SocketAddress getDestination() {
            return destination;
        }

        @Override
        public String toString() {
            return message.toString();
        }
    }
}
